Skip to content

gh-151763: Fix OOM-0014 crash in _interpchannels._channel_id#151902

Open
zainnadeem786 wants to merge 2 commits into
python:mainfrom
zainnadeem786:fix/oom-0014-channel-id
Open

gh-151763: Fix OOM-0014 crash in _interpchannels._channel_id#151902
zainnadeem786 wants to merge 2 commits into
python:mainfrom
zainnadeem786:fix/oom-0014-channel-id

Conversation

@zainnadeem786

Copy link
Copy Markdown

Summary

This PR addresses OOM-0014 from gh-151763.

It fixes a crash in _interpchannels._channel_id() when memory allocation fails while looking up module state.

Issue

channelsmod__channel_id() obtains the owning module with:

PyObject *mod = get_module_from_owned_type(cls);
assert(mod == self);
Py_DECREF(mod);

get_module_from_owned_type() eventually calls _get_current_module(), which allocates the module name using:

PyUnicode_FromString(MODULE_NAME_STR)

Under out-of-memory conditions this allocation can fail and return NULL with a pending MemoryError.

Before this change, channelsmod__channel_id() assumed the helper could never fail.

As a result:

  • Debug builds abort at:
assert(mod == self);

because mod == NULL.

  • Release builds compile out the assertion and continue to:
Py_DECREF(mod);

which dereferences NULL and results in an access violation / segmentation fault.

Root Cause

The helper get_module_from_owned_type(cls) returns a new reference on success but can legitimately return NULL when _get_current_module() fails during module-name allocation.

channelsmod__channel_id() did not check for that failure before using the returned object.

Fix

Add an explicit NULL check immediately after obtaining the module:

PyObject *mod = get_module_from_owned_type(cls);
if (mod == NULL) {
    return NULL;
}
assert(mod == self);
Py_DECREF(mod);

This preserves the existing invariant check while correctly propagating the pending MemoryError instead of aborting or crashing.

Validation

I reproduced the issue locally on both debug and release builds.

Before the fix

Debug build:

Assertion failed: mod == self
Modules/_interpchannelsmodule.c
Fatal Python error: Aborted

Release build:

Windows fatal exception: access violation

After the fix

The same OOM path now returns a clean MemoryError and no longer aborts or crashes.

Regression Test

Added a focused subprocess regression test in:

Lib/test/test__interpchannels.py

The test:

  • uses _testcapi.set_nomemory(0, 1)
  • exercises _interpchannels._channel_id(0)
  • verifies that the subprocess exits normally
  • verifies that MemoryError is propagated instead of aborting or crashing

The test is skipped under Py_TRACE_REFS, matching the existing limitations of _testcapi.set_nomemory().

Tests

Executed:

PCbuild/amd64/python_d.exe -m test test__interpchannels

Result:

== Tests result: SUCCESS ==

1 test OK.

Total tests: run=74 skipped=5

I also verified:

git diff --check

which reports no patch formatting issues (only existing LF/CRLF working-copy warnings).

NEWS

Added a NEWS fragment describing the crash fix and MemoryError propagation.

Addresses OOM-0014 from gh-151763.

Comment thread Lib/test/test__interpchannels.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants